package NoteBook;

import org.junit.Test;

//import ChildAndParent_Extends_modify.Child;
//import ChildAndParent_Extends_modify.Parent;

/**
 * @author Jiang Zhiyan
 *
 * 2021年6月8日 上午11:05:31
 *
 */
/**
 * ！！！变量由编译时类型决定，方法由运行时类型决定 ！！！
 *  instanceof 判断运行时类型 其左侧对象是否为右侧的类或子类  并且需满足，二者的运行时类型相同
 * @author Jiang Zhiyan
 *
 * 2021年4月30日 上午8:56:01
 */

public class _19ParentTest{
	@Test
	public void test01() {
		//实例化一个子类
		Child c1= new Child();
	     c1.x=100;
	     c1.y=200;
	     c1.child=250;
	     c1.show();
		//子类属于父类
		//将子类的实例赋给父类类型的变量（向上转型—）
		//变量p1的类型为Parent，称为编译时类型
		//new关键字使用Child类型，称为运行时类型
	     //多态：当编译时类型与运行时类型不一致——多态，其具体表现形式为方法的重载和方法的重写
//	     代码复用：子类继承父类非私有的属性和方法，扩展父类，实现代码复用
		Parent p1=new Child();
//         p1.x=100;
//         p1.y=200;
////         p1.child=111;  编译失败，p1的编译时类型为Parent类型，Parent没有child资源。
//         p1.show();
		
       //方法的运行由运行时的类型决定
         p1.show();
         System.out.println("---");
         //通过属性访问数据称为静态访问（编译时类型决定）
//         System.out.println(p1.data);
         //通过方法访问数据称为动态访问（运行时类型决定）
         p1.show();

	}
    
@Test
public void test02() {
   Child c1 = new Child();
   Parent p1 = new  Parent();
   Parent p2=c1;
 //强制转换不会报错（向下转型）
//   Child c2=(Child)p1;   编译通过，运行时报错ClassCaseException 类型转换的异常
   //父类类型的实例必须是子类类型。
   Parent p3=new Child();  //区别在于p3运行时类型为子类类型
   Child c2=(Child)p3;
// value  instanceof Type 作用是判断一个变量（value）的实际运行时的类型是否为Type或者Type的子类，如果时，返回True
   System.out.println(p1 instanceof Child);//flase  编译时类型为父类，运行时类型为父类
   System.out.println(p3 instanceof Child);//true   编译时类型为父类，运行时类型为子类   
}
}

//父类
 class Parent{
   int x;
   int y;
  public void show() {
	  System.out.println("parent");
  }
  public long add(long a,long b) {
	  return a+b;
  }
}
//子类
 class Child extends Parent{
     	 int child;
     	 /**
     	  * 方法重写 @Override
     	  * 
     	  * 1.子类对父类非私有的方法进行重新定义。
     	  * 2.java中可以使用@Override注解方法判断该方法是否为重写
     	  * 
     	  * 方法重写的规则
     	  * 
     	  * 1.重写方法名 和 参数类型列表 必须和父类的方法完全一致
     	  * 2.重写的方法的 返回值类型 必须与父类方法的返回值类型一致
     	  * 3.重写的方法的 访问修饰符 必须大于等于父类的方法访问修饰符
     	  */
     	public void show() {
     		System.out.println("child");
     	}
     	@Override   //判断此下方法是否为方法重写
     	public long add(long a,long b) {
     		return a*b;
     	}
 }